/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package comunicacao;

import com.google.code.eventsonfire.EventHandler;
import com.google.code.eventsonfire.Events;
import comunicacao.MessageRedirectorInterface;
import comunicacao.ReceiveMessageInterface;
import comunicacao.RmiAppInterface;
import entities.Server;
import entities.Teatro;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import main.DataWatcherRunnable;
import main.Principal;

/**
 *
 * @author Leonardo Lino Nº45340
 * @author Diogo Pires Nº40351
 */
public class DBServerConnector {

    private static boolean SHOW_ERROR = false;

    MessageRedirectorInterface redirector;
    ReceiveMessageInterface dbServer;
    Registry registry;
    Server server;
    GestorZooKeeper2 gestorZK;
    Server primary;

    public DBServerConnector(GestorZooKeeper2 gestorZK) {
        this.gestorZK = gestorZK;
        primary = this.gestorZK.getPrimary();
        Events.bind(DataWatcherRunnable.class, this);
    }

    @EventHandler
    public void onEvent(EventoElectPrimary event) {
        System.out.println("Elected no primary");
        primary = gestorZK.getPrimary();

        if (primary == null) {
            Events.fire(this, "ERRO: new DB Primary");
        } else {
            Events.fire(this, "new DB Primary");
        }
    }

    public Teatro getTheater(String theaterName) {
        try {

            server = getCorrectDBServer(theaterName);

            if (!parteComum(server)) {
                return null;
            }

            return dbServer.getTheater(theaterName);
        } catch (RemoteException e) {
            if (SHOW_ERROR) {
                System.err.println(e.toString());
            }
            return null;
        }
    }

    public ArrayList<String> listTheaters() {
        try {

            comumPrimary(primary);
            String res = redirector.listTheaters();

            String[] pieces = res.split(":");
            Server server = new Server(pieces[0], Integer.parseInt(pieces[1]));
            server.setRmiBindName(pieces[2]);

            parteComum(server);

            return dbServer.listTheaters();
        } catch (RemoteException e) {
            return null;
        }
    }

    private Server getCorrectDBServer(String teatroNome) throws RemoteException {

        comumPrimary(primary);
        String res = redirector.getResponsible(teatroNome);

        String[] pieces = res.split(":");
        Server server = new Server(pieces[0], Integer.parseInt(pieces[1]));
        server.setRmiBindName(pieces[2]);

        return server;
    }

    private boolean comumPrimary(Server server) {
        try {
            registry = LocateRegistry.getRegistry(
                    server.getIp(), server.getPort());

            // look up the remote object
            redirector = (MessageRedirectorInterface) (registry.lookup(server.getRmiBindName()));

        } catch (RemoteException e) {
            if (SHOW_ERROR) {
                e.printStackTrace();
            }
            return false;
        } catch (NotBoundException e) {
            if (SHOW_ERROR) {
                e.printStackTrace();
            }
            return false;
        }
        return true;
    }

    private boolean parteComum(Server server) {

        try {
            registry = LocateRegistry.getRegistry(
                    server.getIp(), server.getPort());

            // look up the remote object
            dbServer = (ReceiveMessageInterface) (registry.lookup(server.getRmiBindName()));

        } catch (RemoteException e) {
            if (SHOW_ERROR) {
                e.printStackTrace();
            }
            return false;
        } catch (NotBoundException e) {
            if (SHOW_ERROR) {
                e.printStackTrace();
            }
            return false;
        }
        return true;

    }

    public boolean removeSeatReserve(String theaterName, int lugarID, int userID) {
        boolean result = false;

        try {

            server = getCorrectDBServer(theaterName);

            if (!parteComum(server)) {
                return false;
            }

            result = dbServer.removeSeatReserve(theaterName, lugarID, userID, false);
            return result;
        } catch (RemoteException e) {
            return false;
        }

    }

    public boolean reserveSeat(String theaterName, int lugarID, int userID, String timestamp) {
        try {

            server = getCorrectDBServer(theaterName);

            if (!parteComum(server)) {
                return false;
            }

            return dbServer.reserveSeat(theaterName, lugarID, userID, timestamp, false);
        } catch (RemoteException e) {
            return false;
        }
    }

    public boolean purchaseSeat(String theaterName, int lugarID, int userID) {
        try {

            server = getCorrectDBServer(theaterName);

            if (!parteComum(server)) {
                return false;
            }

            return dbServer.purchaseSeat(theaterName, lugarID, userID, false);
        } catch (RemoteException e) {
            return false;
        }
    }

}
